#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@NAME          : validate_data.py
@TIME          : 2025/03/01 16:30:00
@AUTHOR        : chenlip
@VERSION       : 0.1.0
@DESCRIPTION   : 业务数据验证服务类
'''

import re
from flask import request, g
from app.common.security import sanitize_input # 导入清洗函数
from app.common.error_codes import ErrorCode

# 预定义验证规则 - 统一所有业务验证规则
VALIDATION_RULES = {
    # 用户基本信息验证规则
    'username': [
        ('required', '用户名不能为空'),
        (lambda v: re.match(r'^[\u4e00-\u9fa5a-zA-Z0-9_]{2,20}$', v), 
         '用户名只能包含中文、英文、数字和下划线，长度2-20个字符')
    ],
    'nickname': [
        ('required', '昵称不能为空'),
        (lambda v: len(v) <= 30, '昵称长度不能超过30个字符')
    ],
    'password': [
        ('required', '密码不能为空'),
        (lambda v: len(v) >= 6, '密码长度不能少于6个字符')
    ],
    'email': [
        ('required', '邮箱不能为空'),
        (lambda v: re.match(r'^[\w\.-]+@[\w\.-]+\.\w+$', v), '邮箱格式不正确')
    ],
    'email_optional': [
        (lambda v: not v or re.match(r'^[\w\.-]+@[\w\.-]+\.\w+$', v), '邮箱格式不正确')
    ],
    'phone': [
        (lambda v: not v or re.match(r'^\+?[0-9]{10,15}$', v), '手机号格式不正确')
    ],
    'qq': [
        (lambda v: not v or re.match(r'^[1-9][0-9]{4,10}$', v), 'QQ号格式不正确')
    ],
    'id_card': [
        (lambda v: not v or re.match(r'^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dX]$', v), 
         '身份证号格式不正确')
    ],
    'birthday': [
        (lambda v: not v or re.match(r'^\d{4}-\d{2}-\d{2}$', v), '生日格式不正确')
    ],
    'description': [
        (lambda v: not v or len(v) <= 500, '简介长度不能超过500个字符')
    ]
}

class ValidateData:
    """数据验证类"""

    @staticmethod
    def get_sanitized_form(_request):
        """惰性获取清洗后的表单数据"""
        if not hasattr(g, 'sanitized_form'):
            if _request.form:
                g.sanitized_form = sanitize_input(_request.form.to_dict())
            elif _request.is_json:
                g.sanitized_json = sanitize_input(_request.get_json())
            else:
                g.sanitized_json = {}

        if request.is_json:
            form_data = getattr(g, 'sanitized_json', {})
        else:
            form_data = getattr(g, 'sanitized_form', {})
        
        return form_data

    @staticmethod
    def _validate_field(value, field_rule):
        """
        内部方法：验证字段
        
        Args:
            value: 字段值
            field_rule: 验证规则
            
        Returns:
            (bool, str): (验证是否通过, 错误消息)
        """
        # 规则可能是VALIDATION_RULES中的键或直接规则列表
        rules = VALIDATION_RULES.get(field_rule, field_rule) if isinstance(field_rule, str) else field_rule
        
        # 对无值但必填的情况进行检查
        if not value and any(r[0] == 'required' for r in rules):
            return False, next(r[1] for r in rules if r[0] == 'required')
            
        # 检查其他规则
        for validator, error_msg in rules:
            # 跳过必填检查，已在前面处理
            if validator == 'required':
                continue
                
            # 执行验证
            if callable(validator) and not validator(value):
                return False, error_msg
        
        return True, ""

    @staticmethod
    def validate_profile_data(data):
        '''
        验证用户个人资料表单数据
        
        Args:
            data: 表单数据字典
            
        Returns:
            Dict: 包含验证结果的字典
                成功: {"success": True, "code": "10000", "message": "验证通过", "data": None}
                失败: {"success": False, "code": "60014", "message": "错误消息", "data": None}
        '''
        # 定义要验证的字段和规则
        fields_to_validate = {
            'nickname': 'nickname',
            'email': 'email_optional',
            'phone': 'phone',
            'qq': 'qq',
            'id_card': 'id_card',
            'birthday': 'birthday',
            'description': 'description'
        }
        
        # 依次验证每个字段
        for field, rule in fields_to_validate.items():
            value = data.get(field, '')
            if value:  # 只验证有值的字段
                is_valid, error_msg = ValidateData._validate_field(value, rule)
                if not is_valid:
                    return ErrorCode.error_response("60014", error_msg)
        
        # 所有验证通过
        return ErrorCode.success_response(None, "用户更新个人信息验证通过")

    @staticmethod
    def validate_register_data(data):
        """
        验证注册表单数据
        
        Args:
            data: 注册表单数据
            
        Returns:
            Dict: 包含验证结果的字典
                成功: {"success": True, "code": "10000", "message": "验证通过", "data": data}
                失败: {"success": False, "code": "60015", "message": "错误消息", "data": errors}
        """
        errors = {}
        
        # 使用预定义规则验证每个字段
        fields_to_validate = {
            'loginname': 'username',
            'nickname': 'nickname',
            'email': 'email',
            'phone': 'phone'
        }
        
        # 验证基本字段
        for field, rule in fields_to_validate.items():
            value = data.get(field, '')
            is_valid, error_msg = ValidateData._validate_field(value, rule)
            if not is_valid:
                errors[field] = error_msg
        
        # 验证密码
        password = data.get('password', '')
        is_valid, error_msg = ValidateData._validate_field(password, 'password')
        if not is_valid:
            errors['password'] = error_msg
            
        # 验证确认密码
        confirm_password = data.get('confirm_password', '')
        if not confirm_password:
            errors['confirm_password'] = "确认密码不能为空"
        elif password != confirm_password:
            errors['confirm_password'] = "两次输入的密码不一致"
        
        # 如果有错误，返回首个错误
        if errors:
            return {
                "success": False, 
                "code": "60015", 
                "message": next(iter(errors.values())),
                "data": errors
            }
        
        return {
            "success": True,
            "code": "10000",
            "message": "验证通过",
            "data": data
        }

